let arr = [1, 2, 3, [4, 5]]
// ctrl + win + t/i
const isObject = (target) => {
    // 排除null
    if (!target){ return false }
    return typeof target === 'object'
}
const isA = (target) => {
    return Array.isArray(target)
}
// 监听器 
/** 
 * @param {val: object}
 */
// class 不存在变量提升
class Observe {
    constructor(val){
        this.val = val
        this.walk()
    }
    walk(){
        const keys = Object.keys(val)
        for(let k in keys){
            defineReactive(this.val, k, this.val[k])
        }
    }
}
// 订阅器
class Dep {
    constructor() {
        this.subs = []
    }
    depend() {
        if(window.target){
            this.addSub(window.target)
        }
    }
    addSub(sub){
        this.subs.push(sub)
    }
    removeSub(sub){
        const index = this.subs.indexOf(sub)
        if(index > -1){
            this.subs.splice(index, 1)
        }
    }
    notify () {
        for(let sub of this.subs){
            // 传参是个问题
            // 不过响应式的数据都是根据Data对象上的数据来的，数据变化-->通知变化，不存在传参
            sub.update()
        }
    }
}
function parsePath (target, expOrFn) {
    if(typeof expOrFn === 'function'){
        return expOrFn
    }
    // 判断是否是合法keyPath --- a.b.c
    // const test = 
    // if (!expOrFn.test(test)) {}
    const paths = expOrFn.split('.')
    let obj = target
    for(let p of paths){
        // Object.defineProperty 后赋给一个变量，使用这个变量访问属性会触发getter
        obj = target[p]
    }
    return target
}
// 订阅者
class Wathcer {
    constructor(vm, expOrFn, callback){
        this.cb = callback
        this.vm = vm
        this.getter = parsePath(expOrFn)
    }
    get(){
        window.target = this
        this.getter()
        window.target = null
    }
}
/**
 * @name: defineReactive
 * @param {target, key, val}
 * @return {*}
 */
 function defineReactive (target, key, val) {
    if(!isObject(target)) {
        console.warn('not a object')
        return
    } 
    if (isObject(target[key])){
        const keys = Object.keys(target[key])
        console.log(keys)
        for(let k in keys){
            defineReactive(target[key], k, target[key][k])
        }
    }
    let Dep = new Dep()
    Object.defineProperty(target, key, {
        enumerable: true, 
        configurable: true, 
        get: function() {
            // 收集依赖
            console.log('i am getter', val)
            return val
        },
        set: function(newVal) {
            if(newVal === val){ return }
            // 通知更新
            Dep.notify()
            console.log('i am setter')
        }
    })
} 